"""
八、按以下要求用BeautifulSoup来写爬虫

    1. 获取页面 https://github.com/trending/developers 上的信息
    2. 获取每一个开发者的以下信息：
        1. 名字
        2. 仓库的总数
        3. 所有仓库的以下信息：
            名字
            描述
            标签
            语言
            星星的数量
            fork的数量
            授权协议的名字
            最近的更新时间

            ** 如果仓库有多个页面，就翻页
        4. 可以给程序提供一个命令行参数，用来控制抓取的仓库的数量

        注意事项：不同的开发者，其仓库列表的排版可能不同，需要确定
"""
import requests
from bs4 import BeautifulSoup as BS
import re


def fetch(url):
    print('fetching page %s' % url)
    r = requests.get(url)
    if r.ok:
        return r.text
    else:
        return ''


def get_developer_urls(html):
    soup = BS(html, 'lxml')
    for h2 in soup('h2'):
        yield base_url + h2.a['href']


def fetch_all(urls):
    for url in urls:
        name = url.split('/')[-1]
        record = fetch_developer_info(url)
        record['developer'] = name
        yield record


def fetch_developer_info(url):
    """
    名字
    描述
    标签
    语言
    星星的数量
    fork的数量
    授权协议的名字
    最近的更新时间
    """
    # 个人用户的信息页面需要有 ?tab=repositories 才能显示仓库信息
    # 公司用户直接显示的就是仓库信息，这里统一加上 ?tab=repositories
    # 不过，个人类型和公司类型的帐号，其仓库信息页面的结构是不同的，
    # 因此以下代码仍需调整。

    url += '?tab=repositories'
    html = fetch(url)
    soup = BS(html, 'lxml')
    if not len(soup):
        print('error')

    total_repos = int(soup.find('span', class_='Counter').string.replace(',', ''))
    repos = []
    for li in soup.find('div', class_=re.compile('repo-list')).find_all('li'):
        name = li.a.string.strip()
        desc = li.find(itemprop='description').string.strip()
        tags_cont = li.find(class_=re.compile('topics-row-container'))
        if tags_cont:
            tags = [a.string.strip() for a in tags_cont('a')]
        else:
            tags = []

        div = li('div')[-1]
        language = div.find(itemprop='programmingLanguage').string.strip()
        stars, forks =[int(a.text.strip()) for a in div('a', limit=2)]
        license = [span.text.strip() for span in div('span') if
                    span.find(class_=re.compile('octicon-law'))]
        if not license:
            license = None
        mtime = div.find('relative-time')['datetime']
        repo = dict(name=name, desc=desc, tags=tags, language=language,
                    stars=stars, forks=forks, license=license, mtime=mtime)
        repos.append(repo)
        print('fetched repo: %s' % name)
    return {'repos': repos, 'repo_num': len(repos)}


if __name__ == '__main__':
    base_url = 'https://github.com'
    url = 'https://github.com/trending/developers'
    ofile = open('github_developer_infos.jl', 'w')
    html = fetch(url)
    urls = get_developer_urls(html)
    records = fetch_all(urls)
    for record in records:
        print('fetched info of developer: %s' % record['developer'])
        ofile.write(json.dumps(record) + '\n')
        ofile.flush()
    ofile.close()
